#ifndef DBC_CONFIG_H_
#define DBC_CONFIG_H_

#include <map>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>

using namespace std;

#define JSONCPP_OSTRINGSTREAM std::ostringstream

# define JSON_FAIL_MESSAGE(message)                                            \
  {                                                                            \
      throw runtime_error(message); \
  }

#define JSON_ASSERT_MESSAGE(condition, message)                                \
  if (!(condition)) {                                                          \
    JSON_FAIL_MESSAGE(message);                                                \
  }


#define JSON_ASSERT_UNREACHABLE assert(false)

enum ValueType
{
	StringValue,
	IntValue,
	UIntValue,
	ArrayValue,
	ObjectValue,
	NullValue,
};

enum Ret
{
    open_file_error = 1,
    invalid_data,
};

class Value
{
public:
 	static Value const & nullSingleton();

	//Value():type_(NullValue){}

 	//某个键值是否存在
 	bool IsKeyExist(const char * key);

 	Value & operator [] (const char * key);
 	Value & operator [] (const string & key);
 	Value & operator [] (int index);

 	~Value();

 	typedef map<string, Value> ObjectValues;
 	typedef ObjectValues::iterator ObjectIterator;

 	Value(ValueType type = NullValue);

 	Value(const char * value);

 	Value(int value);

 	Value(unsigned value);

 	Value(string & value);

 	Value(const Value & other);

 	Value & operator=(const Value & other);

 	void SetValueType(ValueType type = NullValue);

 	void SetStringValue(const char * value);

 	void SetStringValue(const string & value);

 	void SetIntValue(int value);

 	void SetUIntValue(unsigned value);

 	string AsString();

 	int AsInt();

 	unsigned AsUInt();

 	int Size();

 	void Print();

 	ValueType GetType() {return type_;}

 	friend ostream & operator <<(ostream & out, Value & val);

private:
 	void Release();

 	void Copy(const Value & other);
private:
	union ValueHolder {
	    int int_;
	    unsigned uint_;
	    char* string_;  // actually ptr to unsigned, followed by str, unless !allocated_
	    ObjectValues * map_;
	} value_;

	//ObjectValues childs;

	ValueType type_;   //值类型

	//如何保存value的值呢？？
};

class ConfReader
{
public:
	ConfReader():currentline(0){}

	int Read(const char * filename, Value & val);

    const string & GetErrmsg() const {return errmsg;}
private:
	int ParseObject(Value & current, string key);

	int ParseObjectBegin(string & cont, Value & current, int start, int end);

	int ParseObjectEnd(string & cont, string & expectkey, int start, int end);

	int ParseInt(Value & current, string & content);

	int ParseString(Value & current, string & content);

	int ParseArray(Value & current, string & content);

	bool IsNumber(string & content);

	void SplitString(string & str, char delim, vector<string> & results);

	void TrimString(string & str);
private:
	ifstream input;
	string errmsg;
	int currentline;
};

#endif //DBC_CONFIG_H_

